package org.freedoit.dao;

// Generated Oct 11, 2012 3:54:06 PM by Hibernate Tools 3.4.0.CR1

import com.objectdb.o._NoResultException;
import java.util.Calendar;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import org.apache.log4j.Logger;
import org.freedoit.common.util.SharedConstants;
import org.freedoit.exception.ServerException;
import org.freedoit.om.Task;
import org.freedoit.util.LogUtils;


/**
 * Home object for domain model class Task.
 * @see org.freedoit.om.Task
 * @author Hibernate Tools
 */
public class TaskDAO {

	private static final Logger log = LogUtils.getLogger(TaskDAO.class);

	public void persist(Task task) {
		log.debug("persisting Task instance");
        EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
        try {
            em.getTransaction().begin();
            em.persist(task);
            em.getTransaction().commit();
            log.debug("persist successful");
        } catch (RuntimeException re) {
            log.error("persist failed", re);
            throw new ServerException(re);
        } finally {
            em.close();
        }
	}

	public void delete(Task task) {
		log.debug("deleting Task instance");
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
            em.getTransaction().begin();
            // We don't have a reference to the selected Product.
            // So we have to look it up first,
            task = em.find(Task.class, task.getSerialNo(), LockModeType.WRITE);
            task.setStatus(SharedConstants.DELETED_INTEGER);
            task.setSynced(false);
            em.remove(task);

            em.getTransaction().commit();
            log.debug("delete successful");
		} catch (RuntimeException re) {
                    log.error("delete failed", re);
                    throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public void updateTaskSynced(Long serialNo, Long taskId, Long Timestamp) {
		log.debug("updating Task instance");
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
			em.getTransaction().begin();
            Task task = em.find(Task.class, serialNo, LockModeType.WRITE);
            
            if (taskId != null) {
                task.setTaskId(taskId);
            }
            task.setSynced(true);
            task.setLastModifyTime(Timestamp);
			em.merge(task);
			em.getTransaction().commit();
			log.debug("update successful");
		} catch (RuntimeException re) {
			log.error("update failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public void update(Task task) {
		log.debug("updating Task instance");
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
			em.getTransaction().begin();
			em.merge(task);
			em.getTransaction().commit();
			log.debug("update successful");
		} catch (RuntimeException re) {
			log.error("update failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public void saveOrUpdate(Task task) {
		log.debug("updating Task instance");
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
			em.getTransaction().begin();
            Task taskExisted = findByTaskId(task.getTaskId(), false);
            
            if (taskExisted != null) {
                task.setSerialNo(taskExisted.getSerialNo());
            }
			em.merge(task);
			em.getTransaction().commit();
			log.debug("update successful");
		} catch (RuntimeException re) {
			log.error("update failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public Task findById(Long id) {
		log.debug("getting Task instance with id: " + id);
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
			Task instance = em.find(Task.class, id);
			if (instance == null) {
				log.debug("get successful, no instance found");
			} else {
				log.debug("get successful, instance found");
			}

            if (SharedConstants.ACTIVE_INTEGER.compareTo(instance.getStatus()) != 0) {
                instance = null;
            }
			return instance;
		} catch (RuntimeException re) {
			log.error("get failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public Task findByTaskId(Long taskId) {
        return findByTaskId(taskId, true);
    }

	public Task findByTaskId(Long taskId, boolean onlyActive) {
		log.debug("finding Task instances by user id:" + taskId);
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
			StringBuffer sbQuery = new StringBuffer();
			sbQuery.append("select from ").append(Task.class.getName());
			sbQuery.append(" t where t.taskId = ").append(taskId);
            
            if (onlyActive) {
                sbQuery.append(" and t.status = ").append(SharedConstants.ACTIVE_INTEGER);
            }
                        
            TypedQuery<Task> q = em.createQuery(sbQuery.toString(), Task.class);
			Task result = q.getSingleResult();
			//log.debug("find by user id successful, result size: " + results.size());
			return result;
		} catch (_NoResultException e) {
			log.warn("Warning: no result find", e);
            return null;
        } catch (RuntimeException re) {
			log.error("find by user id failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public List<Task> getTaskListOfTomorrow() {
        Calendar c = Calendar.getInstance();
        c.roll(Calendar.DATE, 1);
		return getTaskListByDate("=", new java.sql.Date(c.getTimeInMillis()));
    }

	public List<Task> getTaskListOfFuture() {
        Calendar c = Calendar.getInstance();
        c.roll(Calendar.DATE, 2);
		return getTaskListByDate(">=", new java.sql.Date(c.getTimeInMillis()));
    }

	public List<Task> getTaskListOfToday() {
		return getTaskListByDate("<=", new java.sql.Date(System.currentTimeMillis()));
	}

	public List<Task> getTaskListByDate(String opt, java.sql.Date date) {
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
			StringBuffer sbQuery = new StringBuffer();
			sbQuery.append("select from ").append(Task.class.getName());
			sbQuery.append(" t where t.startDate ").append(opt).append(" :startDate");
			sbQuery.append(" and t.finished = :finished");
                        
            TypedQuery<Task> q = em.createQuery(sbQuery.toString(), Task.class);
            q.setParameter("startDate", date, TemporalType.DATE);
            q.setParameter("finished", Boolean.FALSE);
			List<Task> results = q.getResultList();
			log.debug("find by user id successful, result size: " + results.size());
			return results;
		} catch (RuntimeException re) {
			log.error("find by user id failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public List<Task> getTaskListOfFinished() {
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
			StringBuffer sbQuery = new StringBuffer();
			sbQuery.append("select from ").append(Task.class.getName());
			sbQuery.append(" t where t.finished = :finished");
                        
            TypedQuery<Task> q = em.createQuery(sbQuery.toString(), Task.class);
            q.setParameter("finished", Boolean.TRUE);
			List<Task> results = q.getResultList();
			log.debug("find by user id successful, result size: " + results.size());
			return results;
		} catch (RuntimeException re) {
			log.error("find by user id failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public List<Task> getTaskListOfCollector() {
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
        CriteriaBuilder cb = em.getCriteriaBuilder();
		try {
			StringBuffer sbQuery = new StringBuffer();
			sbQuery.append("select from ").append(Task.class.getName());
			sbQuery.append(" t where t.startDate is null and t.finished = :finished");
                        
            TypedQuery<Task> q = em.createQuery(sbQuery.toString(), Task.class);
            q.setParameter("finished", Boolean.FALSE);
			List<Task> results = q.getResultList();
			log.debug("find by user id successful, result size: " + results.size());
			return results;
		} catch (RuntimeException re) {
			log.error("find by user id failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public List<Task> findByUserIdAndTimestamp(Long userId, Long timestamp) {
		log.debug("finding Task instances by user id and timestamp:" + userId + " " + timestamp);
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
			StringBuffer sbQuery = new StringBuffer();
			sbQuery.append("select from ").append(Task.class.getName());
			sbQuery.append(" t where t.userId = ").append(userId);
			sbQuery.append(" and t.lastModifyTime > ").append(timestamp);
                  
            TypedQuery<Task> q = em.createQuery(sbQuery.toString(), Task.class);
			List<Task> results = q.getResultList();
			log.debug("find by user id and timestamp successful, result size: " + results.size());
			return results;
		} catch (RuntimeException re) {
			log.error("find by user id and timestamp failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}

	public List<Task> getUnsynchronizedTaskList() {
		EntityManager em = DAOFactory.getEntityManagerFactory().createEntityManager();
		try {
			StringBuffer sbQuery = new StringBuffer();
			sbQuery.append("select from ").append(Task.class.getName());
			sbQuery.append(" t where t.synced = ").append(false);
                  
            TypedQuery<Task> q = em.createQuery(sbQuery.toString(), Task.class);
			List<Task> results = q.getResultList();
			log.debug("find by user id and timestamp successful, result size: " + results.size());
			return results;
		} catch (RuntimeException re) {
			log.error("find by user id and timestamp failed", re);
			throw new ServerException(re);
		} finally {
			em.close();
		}
	}
        
}
